home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / libs / mkfifo / nmpserv.c < prev   
C/C++ Source or Header  |  1997-08-21  |  7KB  |  338 lines

  1. /*
  2. ** ****************************************************************************
  3. ** This is the server the mkfifo command connects to. This program creates
  4. ** a named pipe which is used for communication between the mkfifo routine
  5. ** and the server. The mkfifo sends the name of the named pipe, which should
  6. ** be created and then receives the return code.
  7. ** (c) Klaus Gebhardt, 1997
  8. ** ****************************************************************************
  9. */
  10.  
  11. /*
  12. ** ****************************************************************************
  13. ** This was written for the OS/2 port of Octave, but it is not part of Octave!
  14. ** You can use the code UNMODIFIED. If you think changes are necessary,
  15. ** please send me a mail (gebhardt@crunch.ikp.physik.th-darmstadt.de).
  16. ** Thanks,
  17. **   Klaus Gebhardt
  18. ** ****************************************************************************
  19. */
  20.  
  21. #include "mkfifo.h"
  22. #include "nmp.h"
  23.  
  24.  
  25. #include <malloc.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29.  
  30.  
  31. /* List of all named pipes */
  32. int _named_pipes_ = 0;
  33. _named_pipe_ *_nmp_list_ = NULL;
  34.  
  35.  
  36. /* For accessing the pipe. */
  37. static APIRET apiret;
  38. static HPIPE  hpipe;
  39. static ULONG  count, dummy = 0;
  40.  
  41.  
  42. /* Name and access mode of the pipe */
  43. static char name[1024];
  44. static mode_t mode;
  45. static int result;
  46.  
  47.  
  48. /*
  49. ** Add a named pipe to the list of the already existing named pipes and
  50. ** a thread for it. Return 0 on success, -1 on error out of memory, -2 unable
  51. ** to start the thread.
  52. */
  53. static int add_to_nmp_list (const char *name, mode_t mode)
  54. {
  55.   void *next;
  56.   void *prev;
  57.  
  58.   _named_pipe_ *nmp;
  59.  
  60.   nmp = (_named_pipe_ *) malloc (sizeof(_named_pipe_));
  61.   if (!nmp)  return -1;
  62.  
  63.   nmp->name = strdup (name);
  64.   if (!nmp->name)  return -1;
  65.  
  66.   nmp->mode = mode;
  67.  
  68.   /*
  69.   ** Start a new thread to move the data from one end of the pipe
  70.   ** to the other.
  71.   */
  72.  
  73.   DosResetEventSem (_hev_, &dummy);
  74.   nmp->tid = _beginthread (nmp_thread, NULL, 65536, (void *) nmp);
  75.   DosWaitEventSem (_hev_, SEM_INDEFINITE_WAIT);
  76.  
  77.   if ((nmp->tid == -1) || (nmp->result == -1))
  78.     {
  79.       free ((char *) nmp->name);
  80.       free (nmp);
  81.       return -1;
  82.     }
  83.  
  84.   prev = NULL;
  85.   next = (void *) _nmp_list_;
  86.  
  87.   while (next != NULL)
  88.     {
  89.       prev = next;
  90.       next = ((_named_pipe_ *) next)->next;
  91.     }
  92.  
  93.   nmp->prev = prev;
  94.   nmp->next = NULL;
  95.  
  96.   if (prev)  ((_named_pipe_ *) prev)->next = nmp;
  97.   else       _nmp_list_ = nmp;
  98.  
  99.   _named_pipes_++;
  100.  
  101.   return 0;
  102. }
  103.  
  104.  
  105. /*
  106. ** Search for the named pipe, which name is given in the argument, and 
  107. ** return a pointer to its named pipe structure. Return NULL on error.
  108. */
  109. static _named_pipe_ *lookup_nmp_list (const char *name)
  110. {
  111.   void *next;
  112.   void *prev;
  113.  
  114.   prev = NULL;
  115.   next = (void *) _nmp_list_;
  116.  
  117.   while (next != NULL)
  118.     {
  119.       if (!stricmp (((_named_pipe_ *) next)->name, name))
  120.     return ((_named_pipe_ *) next);
  121.  
  122.       prev = next;
  123.       next = ((_named_pipe_ *) next)->next;
  124.     }
  125.  
  126.   return ((_named_pipe_ *) NULL);
  127. }
  128.  
  129.  
  130. /* Remove a named pipe from the list. */
  131. static int remove_nmp_from_list (const char *name)
  132. {
  133.   void *next;
  134.   void *prev;
  135.  
  136.   _named_pipe_ *nmp;
  137.  
  138.   nmp = lookup_nmp_list (name);
  139.  
  140.   if (nmp)
  141.     {
  142.       prev = nmp->prev;
  143.       next = nmp->next;
  144.  
  145.       if (prev)  ((_named_pipe_ *) prev)->next = next;
  146.       else       _nmp_list_ = next;
  147.  
  148.       if (next)  ((_named_pipe_ *) next)->prev = prev;
  149.  
  150.       nmp->tid = -1;
  151.  
  152.       _named_pipes_--;
  153.  
  154.       free (nmp);
  155.  
  156.       return 0;
  157.     }
  158.  
  159.   return -1;
  160. }
  161.  
  162.  
  163. /* Replace all '/' in name with '\\' */
  164. static void os2_path ()
  165. {
  166.   char *c;
  167.   c = name;
  168.  
  169.   while (*c)
  170.     {
  171.       if ((*c) == '/')  (*c) = '\\';
  172.       c++;
  173.     }
  174. }
  175.  
  176.  
  177. /* Create a new named pipe. */
  178. static int create_nmp ()
  179. {
  180.   int rc;
  181.  
  182.   apiret = DosRead (hpipe, &mode, sizeof(mode), &count);
  183.   if (apiret || (count != sizeof(mode)))  return -1;
  184.  
  185.   apiret = DosRead (hpipe, name, sizeof(name), &count);
  186.   if (apiret)  return -1;
  187.  
  188.   os2_path ();
  189.  
  190.   if (lookup_nmp_list (name))  rc = -1;
  191.   else                         rc = add_to_nmp_list (name, mode);
  192.  
  193.   apiret = DosWrite (hpipe, &rc, sizeof(rc), &count);
  194.   if (apiret || (count != sizeof(rc)))  return -1;
  195.  
  196.   return 0;
  197. }
  198.  
  199.  
  200. /* Remove one named pipe. */
  201. static int remove_nmp ()
  202. {
  203.   int rc;
  204.  
  205.   apiret = DosRead (hpipe, name, sizeof(name), &count);
  206.   if (apiret)  return -1;
  207.  
  208.   os2_path ();
  209.  
  210.   rc = remove_nmp_from_list (name);
  211.  
  212.   apiret = DosWrite (hpipe, &rc, sizeof(rc), &count);
  213.   if (apiret || (count != sizeof(rc)))  return -1;
  214.  
  215.   return 0;
  216. }
  217.  
  218.  
  219. /* Send a list of all active named pipes to the client. */
  220. static int list_nmps ()
  221. {
  222.   _named_pipe_ *nmp;
  223.   int i, j;
  224.  
  225.   apiret = DosWrite (hpipe, &_named_pipes_, sizeof(_named_pipes_), &count);
  226.   if (apiret || (count != sizeof(_named_pipes_)))  return -1;
  227.  
  228.   nmp = _nmp_list_;
  229.  
  230.   for (i=0; i<_named_pipes_; i++)
  231.     {
  232.       apiret = DosRead (hpipe, &j, sizeof(j), &count);
  233.       if (apiret || (count != sizeof(j)) || (i != j))  return -1;
  234.  
  235.       apiret = DosWrite (hpipe, nmp->name, strlen (nmp->name) + 1, &count);
  236.       if (apiret || (count != strlen (nmp->name) + 1))  return -1;
  237.  
  238.       nmp = (_named_pipe_ *) nmp->next;
  239.     }
  240.  
  241.   return 0;
  242. }
  243.  
  244.  
  245. /* Tell how many named pipes are closed, before exiting. */
  246. static int close_server ()
  247. {
  248.   apiret = DosWrite (hpipe, &_named_pipes_, sizeof(_named_pipes_), &count);
  249.   if (apiret || (count != sizeof(_named_pipes_)))  return -1;
  250.  
  251.   return 0;
  252. }
  253.  
  254.  
  255. /* Unknown command is sent to the server. */
  256. static int unknown_cmd ()
  257. {
  258.   int error = -1;
  259.  
  260.   apiret = DosWrite (hpipe, &error, sizeof(error), &count);
  261.   if (apiret || (count != sizeof(error)))  return -1;
  262.  
  263.   return 0;
  264. }
  265.  
  266.  
  267. /* The main program for the server. */
  268. int main (int argc, char *argv[])
  269. {
  270.   int mkfifo_cmd;
  271.   int i, noexit = 0;
  272.  
  273.   if (argc > 2)  exit (-1);
  274.  
  275.   if (argc == 2)
  276.     {
  277.       if (stricmp ("--noexit", argv[1]))  exit (-1);
  278.       noexit = 1;
  279.     }
  280.  
  281.   DosCreateEventSem (NULL, &_hev_, 0L, (BOOL32) 0);
  282.  
  283.   /*
  284.   ** Create the named pipe for communication between mkfifo and the server.
  285.   ** This must be a two-way message pipe.
  286.   */
  287.  
  288.   apiret = DosCreateNPipe (_MKFIFO_NAMED_PIPE_, &hpipe, NP_ACCESS_DUPLEX,
  289.                NP_WAIT | NP_TYPE_MESSAGE | NP_READMODE_MESSAGE |
  290.                0x01, 1024L, 1024L, -1);
  291.  
  292.   if (apiret == 231)  return 1;
  293.   if (apiret != 0)    return -1;
  294.  
  295.   do
  296.     {
  297.       if (DosConnectNPipe (hpipe))  goto error;
  298.  
  299.       apiret = DosRead (hpipe, &mkfifo_cmd, sizeof(mkfifo_cmd), &count);
  300.       if (apiret || (count != sizeof(mkfifo_cmd)))  goto error;
  301.  
  302.       switch (mkfifo_cmd)
  303.     {
  304.     case _MKFIFO_CREATE_NMP_:
  305.       result = create_nmp ();
  306.       break;
  307.  
  308.     case _MKFIFO_REMOVE_NMP_:
  309.       result = remove_nmp ();
  310.       break;
  311.  
  312.     case _MKFIFO_LIST_NMPS_:
  313.       result = list_nmps ();
  314.       break;
  315.  
  316.     case _MKFIFO_EXIT_SERVER_:
  317.       if (!noexit)  result = close_server ();
  318.       break;
  319.  
  320.     default:
  321.       result = unknown_cmd ();
  322.       break;
  323.     }
  324.  
  325.       if (DosDisConnectNPipe (hpipe))  goto error;
  326.     }
  327.   while (((mkfifo_cmd != _MKFIFO_EXIT_SERVER_) && (_named_pipes_ > 0)) ||
  328.      noexit);
  329.  
  330.   DosClose (hpipe);
  331.   return 0;
  332.  
  333. error:
  334.   DosDisConnectNPipe (hpipe);
  335.   DosClose (hpipe);
  336.   return result;
  337. }
  338.